#include "InvoicesParser.h"

#include <QTextStream>
#include <QDir>
#include <assert.h>

using namespace ecocity;

bool
InvoicesParser::parse( const QString &file_invoices_csv, Shop *shop )
{
    // expects '/' as directory separator regardless of operating system.
    QFile file( file_invoices_csv );

    if ( !file.exists( ) )
    {
        return false;
    }

    bool result = true;

    if ( !file.open( QFile::ReadOnly ) )
    {
        assert( 0 );
        result = false;
    }

    if( !parse_file( file, shop ) )
    {
        assert( 0 );
        result = false;
    }

    file.close( );

    return result;
}

//---------------------------------------------------------

bool
InvoicesParser::parse_file( QFile &file, Shop *shop )
{
    QTextStream stream( &file );

    while ( !stream.atEnd( ) )
    {
        QString line = stream.readLine( );

        while( line.startsWith( '#' ) )
        {
            line = stream.readLine( );
        }

        std::vector<int> separators =
                separators_in_line( line, ';' );

        // TODO see minimum
        if( separators.size() < 3 )
        {
            assert( 0 );
            return false;
        }

        parse_line( line, shop, ';' );
    }

    return true;
}

//---------------------------------------------------------

void
InvoicesParser::parse_line( const QString &line, Shop *shop, const char separator )
{
    // TODO define enum instead using numbers
    QDate date = QDate::fromString( line.section( separator, DATE, DATE ) );

    int customer_id = line.section( separator, CUSTOMER_ID, CUSTOMER_ID ).toInt( );

    QString customer_name = line.section( separator, CUSTOMER_NAME, CUSTOMER_NAME );

    const Customer* customer = shop->get_customer( customer_id );

    if ( !customer )
    {
        assert( 0 );
        return;
    }

    Invoice invoice( date, *customer );

    // TODO parse all items not only one
    InvoiceItem item = to_invoice_item( line.section( separator, INVOICE_ITEM, INVOICE_ITEM ), customer, shop, ',' );

    invoice.add_item( item );

    shop->add_invoice( invoice );
}

//---------------------------------------------------------

InvoiceItem
InvoicesParser::to_invoice_item( const QString &line, const Customer *customer, Shop *shop, const char separator )
{
    int quantity = line.section( separator, QUANTITY, QUANTITY ).toInt();
    float weight = line.section( separator, WEIGHT, WEIGHT ).toFloat( );
    float discount_rate = line.section( separator, DISCOUNT_RATE, DISCOUNT_RATE ).toFloat( );
    int product_id = line.section( separator, PRODUCT_ID, PRODUCT_ID ).toInt();

    const Product* product = shop->get_product( product_id );

    if( !product )
    {
        assert( 0 );
    }

    InvoiceItem item( customer->type(), *product, quantity, discount_rate );
    item.set_weight( weight );

    return item;
}

//---------------------------------------------------------

std::vector< InvoiceItem >
InvoicesParser::to_invoice_items( const QString &line, const char separator )
{
    std::vector< InvoiceItem > fake;
    return fake;
}

//---------------------------------------------------------

std::vector<int>
InvoicesParser::separators_in_line( const QString& line, const char separator )
{
    std::vector<int> separators;

    int index = line.indexOf( separator, 0 );

    while ( index != -1 )
    {
        separators.push_back( index );
        index = line.indexOf( separator, index+1 );
    }

    return separators;
}

//---------------------------------------------------------

void
InvoicesParser::append_invoice( const Invoice& invoice,
                                const QString& file_name )
{
    QFile file( file_name );

    if ( !file.open( QIODevice::Append ) )
    {
        assert( 0 );
    }

    QTextStream out_stream( &file );

    out_stream << invoice.date().toString( )
               << ";"
               << invoice.customer().id()
               << ";"
               << invoice.customer().name()
               << ";";

    const std::vector< InvoiceItem >& items = invoice.items();
    for( size_t i = 0; i < items.size(); ++i )
    {
        const InvoiceItem& item = items[ i ];

        out_stream << item.quantity() << ","
                   << item.weight() << ","
                   << item.discount_rate() << ","
                   << item.product().id() << ","
                   << item.product().name() << ";";
    }

    out_stream << endl;

    file.close();
}
